﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using PrintServer.Lib;
using Smart.FormDesigner.Printer;
using Newtonsoft.Json;
using ZXing.Common;
using ZXing;

namespace PrintServer
{
    public partial class FormMain : Form
    {
        private List<Socket> ClientSockets;
        private BindingList<string> ClientIPPorts;
        private Socket socketWatch;
        private Socket socketSend;
        private bool IsStart;
        private Action<string> ShowMsgAction;
        private Action<string> ExeCmdAction;
        private Action UpdateListViewDataAction;
        private ControlChange cc = new ControlChange();

        public FormMain()
        {
            InitializeComponent();
            ShowMsgAction += new Action<string>(ShowMsg);
            ExeCmdAction += new Action<string>(ExeCmd);
            UpdateListViewDataAction += new Action(UpdateListViewData);
            ClientSockets = new List<Socket>();
            ClientIPPorts = new BindingList<string>();
            BindingSource bs = new BindingSource(); //实例化对象
            bs.DataSource = ClientIPPorts; //将List<T>绑定到BindingSource中
            lbIps.DataSource = bs; //将BindingSource绑定至最终的使用者（控件）的数据源
        }

        private void FormMain_Load(object sender, EventArgs e)
        {
            //窗体自适应
            cc.x = this.Width;
            cc.y = this.Height;
            cc.setTag(this);
            //让控件在父控件中居中
            //cc.CenterCtr(panel2, true, true);

            foreach (string installedPrinter in PrinterSettings.InstalledPrinters)
            {
                cbxPrinter.Items.Add(installedPrinter);
            }
            cbxPrinter.SelectedIndex = 0;

            var files = Directory.GetFiles(@"Template", "*.xml");
            foreach (var file in files)
                cbxTemp.Items.Add(file);
            cbxTemp.SelectedIndex = 0;

            string name = Dns.GetHostName();
            IPAddress[] ipadrlist = Dns.GetHostAddresses(name);
            foreach (IPAddress ipa in ipadrlist)
            {
                if (ipa.AddressFamily == AddressFamily.InterNetwork)
                    cbxListenIp.Items.Add(ipa.ToString());
            }
            cbxListenIp.SelectedIndex = 0;
        }

        private void FormMain_Resize(object sender, EventArgs e)
        {
            //控件随着窗体改变大小
            float newx = this.Width / cc.x;
            float newy = this.Height / cc.y;
            cc.setControls(newx, newy, this);
            //让控件在父控件中居中
            //cc.CenterCtr(panel2, true, true);
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {
            if (btnConnect.Text == "停止")
            {
                socketSend?.Close();
                IsStart = false;
                timer1.Enabled = IsStart;
                btnListen.Enabled = !IsStart;
                btnConnect.Text = "连接";
                ShowMsg("信息:断开连接!");
            }
            else
            {
                connect();
            }
        }

        private void btnListen_Click(object sender, EventArgs e)
        {
            if (btnListen.Text == "停止") {
                socketWatch?.Close();
                IsStart = false;
                timer1.Enabled = IsStart;
                btnConnect.Enabled = !IsStart;
                btnListen.Text = "监听";
                ShowMsg("信息:停止监听!");
            }
            else
            {
                socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //IPAddress ip = IPAddress.Any;
                IPAddress ip = IPAddress.Parse(cbxListenIp.Text);
                //创建对象端口
                IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtListenPort.Text));

                socketWatch.Bind(point);//绑定端口号
                ShowMsg("信息:监听成功!");

                socketWatch.Listen(100);//允许连接的客户端数量
                Thread thread = new Thread(Listen);//创建监听线程
                thread.IsBackground = true;
                thread.Start(socketWatch);

                IsStart = true;
                timer1.Enabled = IsStart;
                btnConnect.Enabled = !IsStart;
                btnListen.Text = "停止";
            }
            
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            if (!IsStart) return;
            string info = txtSend.Text;
            if (info == "") return;
            if (socketSend == null)
            {
                int index = lbIps.SelectedIndex;
                if (index < 0) return;
                if (ClientSockets.Count <= index) return;
                socketSend = ClientSockets[index];
            }
            ShowMsg(info);
            Send(info);
        }

        private void lbClear_Click(object sender, EventArgs e)
        {
            txtInfo.Text = "";
        }

        private void connect()
        {
            try {
                if (socketSend != null)
                {
                    socketSend.Shutdown(SocketShutdown.Both);
                    socketSend.Disconnect(true);
                    socketSend.Close();
                }
                socketSend = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ip = IPAddress.Parse(txtConnectIp.Text);
                IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtConnectPort.Text));
                socketSend.Connect(point);
                ShowMsg("信息:连接成功!");

                Thread thread = new Thread(Received);
                thread.IsBackground = true;
                thread.Start(socketSend);

                IsStart = true;
                timer1.Enabled = IsStart;
                btnListen.Enabled = !IsStart;
                btnConnect.Text = "停止";

                if (txtSign.Text != "")
                {
                    Send("cmd&sign&" + txtSign.Text);
                }
            }
            catch(Exception e)
            {
                socketSend = null;
                ShowMsg(e.Message);
            }
            
        }

        void Listen(object o)
        {
            try
            {
                Socket socketWatch = o as Socket;
                while (IsStart)
                {
                    socketSend = socketWatch.Accept();//等待接收客户端连接
                    ClientSockets.Add(socketSend);
                    ClientIPPorts.Add(socketSend.RemoteEndPoint.ToString());
                    this.BeginInvoke(UpdateListViewDataAction);
                    this.BeginInvoke(ShowMsgAction, socketSend.RemoteEndPoint.ToString() + ":" + "连接成功!");
                    //开启一个新线程，执行接收消息方法
                    Thread r_thread = new Thread(Received);
                    r_thread.IsBackground = true;
                    r_thread.Start(socketSend);
                }
            }
            catch (Exception ex)
            {
                this.BeginInvoke(ShowMsgAction, "等待客户端监听发生异常:" + ex.Message);
            }
        }

        void Received(object o)
        {
            try
            {
                Socket socketSend = o as Socket;
                if (!socketSend.Connected) return;
                while (IsStart)
                {
                    //客户端连接服务器成功后，服务器接收客户端发送的消息
                    byte[] buffer = new byte[1024 * 1024 * 3];
                    //实际接收到的有效字节数
                    int len = socketSend.Receive(buffer);
                    if (len == 0)
                    {
                        break;
                    }
                    string str = Encoding.UTF8.GetString(buffer, 0, len);
                    if (str.Contains('{')) {
                        this.BeginInvoke(ExeCmdAction, str);
                    }
                    else
                    {
                        this.BeginInvoke(ShowMsgAction, str);
                    }
                }
            }
            catch (Exception ex)
            {
                this.BeginInvoke(ShowMsgAction, "接收客户端内容发生异常:" + ex.Message);
            }
        }

        void Send(string str)
        {
            try
            {
                if (socketSend == null) return;
                byte[] buffer = Encoding.UTF8.GetBytes(str);
                socketSend.Send(buffer);
            }
            catch (Exception ex)
            {
                ShowMsg(ex.Message);
            }

        }

        private void ShowMsg(string msg)
        {
            string info = string.Format("[{0}]#\r\n{1}\r\n", DateTime.Now.ToString("G"), msg);
            txtInfo.AppendText(info);
        }

        private void ExeCmd(string msg)
        {
            try
            {
                Dictionary<string, string> dict = JsonConvert.DeserializeObject<Dictionary<string, string>>(msg);
                string[] orderInfo = dict["orderInfo"].Split('|');
                string userCode = orderInfo[0];
                string orderCount = orderInfo[1];
                string countNumber = orderInfo[2];
                string goodsName = orderInfo[3];
                string price = orderInfo[4];
                string countPrice = orderInfo[5];

                string[] cesDispatch = dict["cesDispatch"].Split('|');
                string dispatchPerson = cesDispatch[0];
                string dispatchPhone = cesDispatch[1];
                string dispatchAddress = cesDispatch[2];

                string[] cesUserAddress = dict["cesUserAddress"].Split('|');
                string consigneeName = cesUserAddress[0];
                string consigneePhone = cesUserAddress[1];
                string consigneeAddress = cesUserAddress[2] + cesUserAddress[3];

                string orderCode1 = "";
                string orderCode2 = "";
                string orderCode3 = "";
                string[] orderCodes = dict["orderCode"].TrimEnd(',').Split(',');
                for (int i = 0; i < orderCodes.Length; i++)
                {
                    if (i < 2)
                    {
                        orderCode1 += orderCodes[i] + ",";
                    }
                    else if(i < 4)
                    {
                        orderCode2 += orderCodes[i] + ",";
                    }
                    else if (i < 6)
                    {
                        orderCode3 += orderCodes[i] + ",";
                    }
                }

                string bottomInfo = "打单日期: " + DateTime.Now.ToString() + " " + dict["realname"];

                //string xzOrder = makeBarcode(dict["xzOrder"]);
                //string waybillNo = makeBarcode(dict["waybillNo"]);
                //string orderNo = makeBarcode("GG"+dict["xzOrder"]);
                //string logo = $"{Application.StartupPath}\\Templete\\logo.png";

                string[] ParsName = { "orderNumber", "dzjm", "invalid",
                    "userCode", "orderCount", "countNumber", "goodsName", "price", "countPrice",
                    "dispatchPerson", "dispatchPhone", "dispatchAddress", "consigneeName", "consigneePhone", "consigneeAddress", 
                    "xzOrder", "waybillNo", "orderNo",
                    "orderCode1", "orderCode2", "orderCode3", "bottomInfo" };
                string[] Pars = { dict["orderNumber"], dict["dzjm"], dict["invalid"],
                    userCode, orderCount, countNumber, goodsName, price, countPrice,
                    dispatchPerson, dispatchPhone, dispatchAddress, consigneeName, consigneePhone, consigneeAddress,
                    dict["xzOrder"], dict["waybillNo"], "GG"+dict["xzOrder"], 
                    orderCode1, orderCode2, orderCode3, bottomInfo };

                char tag = '1';
                if (dict["dzjm"].Length == 2)
                {
                    tag = '2';
                }
                PrinterHelper.Print2XmlEx($"Template\\order_{tag}.xml", "KM-118D", true, ParsName, Pars, out Bitmap bitmap, "105mm x 145mm");
                ShowMsg("打印成功!");
            }
            catch (Exception ex)
            {
                ShowMsg("打印发生异常:" + ex.Message);
            }
        }

        private string makeBarcode(string text)
        {
            string path = $"{Application.StartupPath}\\temp\\";
            if (!Directory.Exists(path)) {
                Directory.CreateDirectory(path);
            }
            EncodingOptions encodeOption = new EncodingOptions();
            encodeOption.Height = 55;
            encodeOption.Width = 237;
            BarcodeWriter wr = new BarcodeWriter();
            wr.Options = encodeOption;
            wr.Format = BarcodeFormat.CODE_39;
            Bitmap img = wr.Write(text);
            string filePath = $"{path}CODE_39-{text}.jpg";
            img.Save(filePath, System.Drawing.Imaging.ImageFormat.Jpeg);
            return filePath;
        }


        private void timer1_Tick(object sender, EventArgs e)
        {
            if (btnConnect.Text == "停止")
            {
                if (socketSend == null || !IsSocketConnected())
                {
                    ShowMsg("重连");
                    connect();
                }
            }
            else if(btnListen.Text == "停止")
            {
                if (ClientSockets.Count == 0) return;
                for (int i = ClientSockets.Count - 1; i >= 0; i--)
                {
                    if (!ClientSockets[i].Connected)
                    {
                        ClientSockets.RemoveAt(i);
                        ClientIPPorts.RemoveAt(i);
                        this.BeginInvoke(UpdateListViewDataAction);
                    }
                }
            }
           
        }

        private void UpdateListViewData()
        {
            lbIps.DataSource = null;
            lbIps.DataSource = ClientIPPorts;
            //listBox1.Items.Clear();
            //for (int i = 0; i < ClientIPPorts.Count; i++)
            //{

            //}
        }

        private bool IsSocketConnected()
        {
            #region 过程
            bool connectState = true;
            bool blockingState = socketSend.Blocking;
            try
            {
                //byte[] tmp = new byte[1];
                //socketSend.Blocking = false;
                //socketSend.Send(tmp, 0, 0);
                byte[] buffer = Encoding.UTF8.GetBytes("1");
                socketSend.Send(buffer);
                connectState = true; //若Send错误会跳去执行catch体，而不会执行其try体里其之后的代码
            }
            catch (SocketException e)
            {
                // 10035 == WSAEWOULDBLOCK
                if (e.NativeErrorCode.Equals(10035))
                {
                    connectState = true;
                }
                else
                {
                    connectState = false;
                }
            }
            finally
            {
                socketSend.Blocking = blockingState;
            }
            return connectState;
            #endregion
        }




        //---------------------------------------------------------------------------------------------------------


        private void btnPrint_Click(object sender, EventArgs e)
        {
            try
            {
                PrinterHelper.Print2XmlEx(cbxTemp.Text, cbxPrinter.Text, true, null, null, out Bitmap bitmap, cbxPage.Text);
                this.pbImg.Image = bitmap;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void btnLabel_Click(object sender, EventArgs e)
        {
            string path = Application.StartupPath;
            System.Diagnostics.ProcessStartInfo myStartInfo = new System.Diagnostics.ProcessStartInfo();
            myStartInfo.FileName = $"{path}/Label/Smart.FormDesigner.Demo.exe";
            System.Diagnostics.Process myProcess = new System.Diagnostics.Process();
            myProcess.StartInfo = myStartInfo;
            myProcess.Start();
            myProcess.WaitForExit(); //等待程序退出
        }

        private void cbxPrinter_SelectedIndexChanged(object sender, EventArgs e)
        {
            cbxPage.Items.Clear();
            String[] strArr = PrinterHelper.GetPrinter(cbxPrinter.Text);
            foreach (string str in strArr)
            {
                cbxPage.Items.Add(str);
            }
            cbxPage.SelectedIndex = 0;
        }

        
    }
}
